package name.nano.client;

import java.util.ArrayList;

import name.nano.client.dto.LocationInTime;
import name.nano.client.dto.PlayerTactic;
import name.nano.client.dto.TeamTactic;
import name.nano.client.enums.DefenceMode;
import name.nano.client.utils.Coordinate;
import name.nano.client.view.MyCanvas;


import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window.Location;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.widgetideas.client.SliderBar;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class FrisbeeTacticBoard implements EntryPoint {
	private MyCanvas m_canvas;
	private Timer m_timer;
	public GameBoard m_gameBoard;
	public boolean m_paused=true;
	private TeamTacticServiceAsync greetingService=GWT.create(TeamTacticService.class);
	
	private UltimatePlayer playerWithDisc;
	private UltimatePlayer selectedPlayer;
	//private MouseListenerImplementation m_mouseListenerImplementation;

	private static final int TIMER_DELAY = 200;

	//private TextBox posAreaX;
	//private TextBox posAreaY;

	private TextBox m_tacticNameField;
	
	protected TeamTactic m_teamTactic;
	public long m_startTime;
	private SliderBar m_slider;
	final Button m_startButton = new Button("start");
	final Button m_resetButton = new Button("reset");
	private long m_currentSimulationTime=0;
	private long m_currentSimulationTargetTime=Long.MAX_VALUE;
	
	public FrisbeeTacticBoard() {
		
		//posAreaX = new TextBox();
		//posAreaY = new TextBox();
		m_tacticNameField=new TextBox();
		m_tacticNameField.setText("stack");
	}
	public UltimatePlayer getSelectedPlayer() {
		return selectedPlayer;
	}
	public void setSelectedPlayer(UltimatePlayer selectedPlayer) {
		this.selectedPlayer = selectedPlayer;
	}
	
	private void setCurrentTime(long ms){
		if (!m_paused){
			toogleAnimation(); //stop running animation
		}
		m_currentSimulationTargetTime=ms;
		m_gameBoard.resetPlayers();
		redraw();
		toogleAnimation(); //start until new target timestamp is reached
	}
	/**
	 * Send the name from the nameField to the server and wait for a response.
	 */
	private void toogleAnimation() {
		if (m_paused){
			m_startTime=System.currentTimeMillis();
			m_timer.schedule(TIMER_DELAY);
			m_startButton.setText("stop");
			m_paused=false;
		} else {
			m_timer.cancel();
			m_paused=true;
			m_startButton.setText("start");
		}
		
	}

	private final class RunAnimationTimer extends Timer {
		@Override
		public void run() {
			if (m_currentSimulationTime<m_currentSimulationTargetTime){
				boolean moreWorkToDo=nextAnimationStep();
				if (moreWorkToDo)
					m_timer.schedule(TIMER_DELAY);
				else
					toogleAnimation();
			} else {
				toogleAnimation();
			}
		}
	}

	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		//final Button resetButton = new Button("reset");
		
		final Button loadButton = new Button("load");
		final Button saveButton = new Button("save");
		// We can add style names to widgets
		m_startButton.addStyleName("sendButton");

		// Use RootPanel.get() to get the entire body element
		RootPanel.get("b2").add(m_startButton);
		//ScrollPanel scrollPanel = new ScrollPanel();
		//scrollPanel.setSize(""+500, ""+40);
		//scrollPanel.setAlwaysShowScrollBars(true);
		//HorizontalPanel vP=new HorizontalPanel();
		FlowPanel flowPanelRight=new FlowPanel();
		
		//vP.add(resetButton);
		//vP.add(startButton);
		  m_slider = new SliderBar(0.0, 30.0);
		  m_slider.setStepSize(1.0);
		  m_slider.setCurrentValue(0.0);
		  m_slider.setNumTicks(10);
		  m_slider.setNumLabels(5);
		  
		  m_slider.setPixelSize(400,50);
		  
		  
		//vP.add(slider);  

		RootPanel.get("b2").add(m_slider);
		m_slider.sinkEvents(Event.ONMOUSEDOWN);
		m_slider.sinkEvents(Event.ONMOUSEUP);
		m_slider.sinkEvents(Event.ONMOUSEMOVE);
		m_slider.sinkEvents(Event.ONBLUR);
		flowPanelRight.add(loadButton);
		flowPanelRight.add(saveButton);
		flowPanelRight.add(m_resetButton);
		flowPanelRight.add(m_startButton);
		
		RootPanel.get("c3").add(m_tacticNameField);
		RootPanel.get("c3").add(flowPanelRight);
	    // draw shapes
	    m_timer=new RunAnimationTimer();
	    m_tacticNameField.setText(Location.getParameter("name"));
	    String tacticName = m_tacticNameField.getText();


	    loadAndShowTactic(tacticName);
	    



		

		// Add a handler to send the name to the server
		StartHandler handler = new StartHandler();
		m_startButton.addClickHandler(handler);
		saveButton.addClickHandler(new SaveHandler());
		loadButton.addClickHandler(new LoadHandler());
		m_resetButton.addClickHandler(new ResetHandler());
		
	}
	class StartHandler implements ClickHandler {
		/**
		 * Fired when the user clicks on the sendButton.
		 */
		public void onClick(ClickEvent event) {
			m_currentSimulationTargetTime=Long.MAX_VALUE;
			FrisbeeTacticBoard.this.toogleAnimation();
		}


	}
	class ResetHandler implements ClickHandler {
		/**
		 * Fired when the user clicks on the sendButton.
		 */
		public void onClick(ClickEvent event) {
			FrisbeeTacticBoard.this.setCurrentTime(0);
		}


	}
	
	class LoadHandler implements ClickHandler {

		@Override
		public void onClick(ClickEvent event) {
			loadAndShowTactic(m_tacticNameField.getText());
		}
		
	}

	class SaveHandler implements ClickHandler {
		/**
		 * Fired when the user clicks on the sendButton.
		 */
		public void onClick(ClickEvent event) {
			ArrayList<UltimatePlayer> players = m_gameBoard.getPlayers();
			UltimatePlayer[] playerArr = players.toArray(new UltimatePlayer[0]);
			for (int i = 0; i < playerArr.length; i++) {
				UltimatePlayer ultimatePlayer = playerArr[i];
				PlayerTactic playerTactic = m_teamTactic.getPlayersTactic()[i];
				playerTactic.setStartLocation(ultimatePlayer.getLocation());
				ArrayList<LocationInTime> moves=new ArrayList<LocationInTime>();
				moves.addAll(ultimatePlayer.getRunningPoints());
				playerTactic.setMoves(moves);
			}
			greetingService.storeTeamTactic(m_tacticNameField.getText(), m_teamTactic, new AsyncCallback<Boolean>(){

				@Override
				public void onFailure(Throwable caught) {
					
					
				}

				@Override
				public void onSuccess(Boolean result) {
					
				}
				
			});
		}
	}

	private void loadAndShowTactic(String tacticName) {
		greetingService.getTeamTactic(tacticName,new AsyncCallback<TeamTactic>(){

			@Override
			public void onFailure(Throwable caught) {
				
				
			}

			@Override
			public void onSuccess(TeamTactic result) {
				if (!m_paused)
					toogleAnimation();
					
				m_slider.setCurrentValue(0);
				FrisbeeTacticBoard frisbeeTacticBoard = FrisbeeTacticBoard.this;
				updateBoardTacticUI(result, frisbeeTacticBoard);
			}
	    });
	}
	protected boolean nextAnimationStep() {
		m_currentSimulationTime=System.currentTimeMillis()-m_startTime;
		m_slider.setCurrentValue(m_currentSimulationTime/1000);
		boolean moreWorkToDo=updateModel();
		redraw();
		return moreWorkToDo;
		
	}
	public void redraw(){
		if (m_gameBoard!=null)
			draw(this.m_gameBoard);
	}
	public long getCurrentSliderValue(){
		return (long) (m_slider.getCurrentValue()*1000);
	}
	private boolean updateModel() {
		
		
		return m_gameBoard.nextStep(m_currentSimulationTime);
		
	}
	private void draw(GameBoard b) {
		b.drawBoard(m_canvas);
	}
	
	public DefenceMode getDefenceMode() {
		return DefenceMode.LEFT_OPEN;
	}

	public Coordinate toLogicalCoordinates(Coordinate pixelCords){
		double sx=getSX();
		double sy=getSY();
		return new Coordinate(pixelCords.x/sx,pixelCords.y/sy);
	}
	public double getSY() {
		return m_canvas.getHeight()/m_gameBoard.getFieldSize().y;
	}
	public double getSX() {
		return m_canvas.getWidth()/m_gameBoard.getFieldSize().x;
	}
	public Coordinate toPixelCoordinates(Coordinate logicalCords){
		double sx=getSX();
		double sy=getSY();
		return new Coordinate(logicalCords.x*sx,logicalCords.y*sy);
	}
	public UltimatePlayer getPlayerWithDisc() {
		return this.playerWithDisc;
	}
	public void setPlayerWithDisc(UltimatePlayer playerWithDisc) {
		this.playerWithDisc = playerWithDisc;
	}
	private void updateBoardTacticUI(TeamTactic result,
			FrisbeeTacticBoard frisbeeTacticBoard) {
		setSelectedPlayer(null);
	    m_teamTactic=result;
		m_gameBoard=new GameBoard(this,result);
		//this.setPlayerWithDisc(m_gameBoard.getPlayers().get(result.getPlayerWithDisk()));
		RootPanel rootPanel = RootPanel.get("canvas");
		if (m_canvas!=null)
			rootPanel.remove(m_canvas);
		
		m_canvas=new MyCanvas(this);
		//m_canvas = new MyCanvas(FrisbeeTacticBoard.this.m_gameBoard);
		//m_mouseListenerImplementation=new MouseListenerImplementation(this);
		
		rootPanel.add(m_canvas);
		
		
		m_canvas.setPixelSize(400, 600);
		
		m_canvas.restore();
		redraw();
	}
}
